package com.sys.system.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sys.common.constant.SSEMessageConstants;
import com.sys.common.core.domain.entity.SysUser;
import com.sys.common.utils.SecurityUtils;
import com.sys.common.sse.SseComponent;
import com.sys.system.domain.SysNotice;
import com.sys.system.domain.SysNoticeUser;
import com.sys.system.domain.vo.SysNoticeVO;
import com.sys.system.mapper.NoticeUserMapper;
import com.sys.system.service.INoticeUserService;
import com.sys.system.service.ISysUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 通知公告用户Service业务层处理
 *
 * @author LGY
 * @date 2025-04-16
 */
@Slf4j
@Service
public class NoticeUserServiceImpl extends ServiceImpl<NoticeUserMapper, SysNoticeUser> implements INoticeUserService {

    @Autowired
    private NoticeUserMapper noticeUserMapper;
    @Autowired
    private SseComponent sseComponent;
    @Autowired
    private ISysUserService sysUserService;
    @Resource(name = "myExecutor")
    private ThreadPoolExecutor executor;

    /**
     * 查询通知公告用户
     *
     * @param id 通知公告用户主键
     * @return 通知公告用户
     */
    @Override
    public SysNoticeUser selectNoticeUserById(String id) {
        return this.getById(id);
    }

    /**
     * 查询通知公告用户列表
     *
     * @param sysNoticeUser 通知公告用户
     * @return 通知公告用户
     */
    @Override
    public List<SysNoticeUser> selectNoticeUserList(SysNoticeUser sysNoticeUser) {
        return noticeUserMapper.selectNoticeUserList(sysNoticeUser);
    }

    /**
     * 新增通知公告用户
     *
     * @param sysNoticeUser 通知公告用户
     * @return 结果
     */

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void insertNoticeUser(SysNoticeUser sysNoticeUser) {
        this.save(sysNoticeUser);
    }

    /**
     * 修改通知公告用户
     *
     * @param sysNoticeUser 通知公告用户
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateNoticeUser(SysNoticeUser sysNoticeUser) {
        this.updateById(sysNoticeUser);
    }

    /**
     * 批量删除通知公告用户
     *
     * @param ids 需要删除的通知公告用户主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteNoticeUserByIds(String[] ids) {
        this.removeBatchByIds(Arrays.asList(ids));
    }

    @Override
    public List<SysNoticeUser> getByUserId(String userId) {
        SysNoticeUser sysNoticeUser = new SysNoticeUser();
        sysNoticeUser.setUserId(userId);
        return noticeUserMapper.selectNoticeUserList(sysNoticeUser);
    }

    @Override
    public List<SysNoticeUser> findByUserIdNonRead(Set<String> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        return new LambdaQueryChainWrapper<>(baseMapper)
                .in(SysNoticeUser::getUserId, userIds)
                .eq(SysNoticeUser::getStatus, 0)
                .list();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteByNoticeIds(List<String> noticeIds) {
        new LambdaUpdateChainWrapper<>(baseMapper)
                .in(SysNoticeUser::getNoticeId, noticeIds)
                .remove();
    }

    @Override
    public List<SysNoticeUser> selectByNoticeId(String noticeId) {
        return new LambdaQueryChainWrapper<>(baseMapper)
                .eq(SysNoticeUser::getNoticeId, noticeId)
                .list();
    }

    /**
     * 根据当前用户查询通知列表
     *
     * @param notice notice
     * @param userId 当前用户id
     * @return
     */
    @Override
    public List<SysNoticeVO> selectNoticeListByCurrentUser(SysNotice notice, String userId) {
        return baseMapper.selectNoticeListByCurrentUser(notice, userId);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updatePersonNoticeHasLike(String id, Integer hasLike) {
        new LambdaUpdateChainWrapper<>(baseMapper)
                .eq(SysNoticeUser::getId, id)
                .set(SysNoticeUser::getHasLike, hasLike)
                .update();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updatePersonNoticeHasRead(String id) {
        new LambdaUpdateChainWrapper<>(baseMapper)
                .eq(SysNoticeUser::getId, id)
                .set(SysNoticeUser::getStatus, 1)
                .update();
        String clientId = SecurityUtils.getUsername();
        executor.execute(() -> {
            sendClientMessage(clientId, SSEMessageConstants.SERVICE_TYPE.NOTICE, SSEMessageConstants.CUSTOM.ADMIN);
            sendClientMessage(clientId, SSEMessageConstants.SERVICE_TYPE.NOTICE, SSEMessageConstants.CUSTOM.USER);
            sendClientMessage(clientId, SSEMessageConstants.SERVICE_TYPE.NOTICE, SSEMessageConstants.CUSTOM.APP);
        });
    }

    @Override
    public void sendClientMessage(String clientId, String type, String custom) {
        boolean connectFlag = sseComponent.isClientConnected(clientId, type, custom);
        if (!connectFlag) {
            log.info("用户 {} - {} - {} 未连接, 无需进行消息发送", clientId, type, custom);
            return;
        }
        // 根据userName查询系统用户
        SysUser sysUser = sysUserService.selectUserByUserName(clientId);
        if (sysUser == null) {
            return;
        }
        SysNoticeUser sysNoticeUser = new SysNoticeUser();
        sysNoticeUser.setUserId(sysUser.getId())
                .setStatus(0);
        List<SysNoticeUser> sysNoticeUserList = this.selectNoticeUserList(sysNoticeUser);
        Integer nonReadCount = CollectionUtils.isEmpty(sysNoticeUserList) ? 0 : sysNoticeUserList.size();
        log.info("通知用户 - {}， 更新未读消息：{}", clientId, nonReadCount);
        sseComponent.sendMessageAsync(clientId, type, custom, String.valueOf(nonReadCount));
    }

    @Override
    public void sendAllUserMessage() {
        executor.execute(() -> {
            Map<String, SseEmitter> currentEmitters = sseComponent.getCurrentEmitters();
            if (currentEmitters.isEmpty()) {
                return;
            }
            currentEmitters.keySet().forEach(clientId -> {
                String[] clientArr = clientId.split("_");
                sendClientMessage(clientArr[0], clientArr[1], clientArr[2]);
            });
        });
    }
}